<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-169911533-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-169911533-1');
</script>

  

  
  <title>JVM 01 类加载器及类加载过程 | 空城盼故人</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="google-site-verification" content="NOVpqBhVVjZHOamocUf3Grijt7xAK_Engoe_FNrxE3Q" />
  <meta name="baidu-site-verification" content="HBrapLOndy" />
  
  <meta name="keywords" content="许嵩老公" />
  
  <meta name="description" content="概述类的加载器及类加载过程 类的加载过程一： Loading 加载 类的加载过程二： Linking 链接 Verification 验证 Preparation 准备 Resolution 解析   类的加载过程三： Initialization 初始化">
<meta property="og:type" content="article">
<meta property="og:title" content="JVM 01 类加载器及类加载过程">
<meta property="og:url" content="https://xiaoyan94.github.io/2020/07/03/JVM-01/index.html">
<meta property="og:site_name" content="空城盼故人">
<meta property="og:description" content="概述类的加载器及类加载过程 类的加载过程一： Loading 加载 类的加载过程二： Linking 链接 Verification 验证 Preparation 准备 Resolution 解析   类的加载过程三： Initialization 初始化">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://xiaoyan94.github.io/2020/07/03/JVM-01/JVM.png">
<meta property="article:published_time" content="2020-07-03T08:13:14.000Z">
<meta property="article:modified_time" content="2020-07-05T13:20:25.691Z">
<meta property="article:author" content="许嵩老公">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="JVM">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://xiaoyan94.github.io/2020/07/03/JVM-01/JVM.png">
  
    <link rel="alternate" href="../../../../atom.xml" title="空城盼故人" type="application/atom+xml">
  
  
    <link rel="icon" href="https://q1.qlogo.cn/g?b=qq&nk=979727728&s=640">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="../../../../css/style.css">

  
<link rel="stylesheet" href="../../../../css/highlight.css">

<meta name="generator" content="Hexo 4.2.1"></head>

<body>
  <div id="fullpage" class="mobile-nav-right">
    <div class="fixed"></div>
    
      <div id="wrapper">
    
    
      <header id="header">
  <div id="nav-toggle" class="nav-toggle"></div>
  <div class="head-box global-width">
    <nav class="nav-box nav-right">
      
        <a class="nav-item" href="../../../../index.html" title
        
        >首页</a>
      
        <a class="nav-item" href="../../../../archives" title
        
        >归档</a>
      
        <a class="nav-item" href="../../../../quick-notes" title
        
        >小抄</a>
      
        <a class="nav-item" href="../../../../about" title
        
        >关于</a>
      
    </nav>
  </div>
</header>
      <div id="middlecontent" title class="global-width sidebar-right">
        <section id="main"><article id="post-JVM-01" class="article global-container article-type-post" itemscope itemprop="blogPost">
  
    <header class="article-header">
      
  
    <h1 class="article-title" itemprop="name">
      JVM 01 类加载器及类加载过程
    </h1>
  

    </header>
  
  <div class="article-meta">
    <a href="" class="article-date">
  <time datetime="2020-07-03T08:13:14.000Z" itemprop="datePublished">2020-07-03</time>
</a>
    
    
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="../../../../tags/JVM/" rel="tag">JVM</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="../../../../tags/Java/" rel="tag">Java</a></li></ul>

  </div>
  
    <span id="busuanzi_container_page_pv">
      本文总阅读量<span id="busuanzi_value_page_pv"></span>次
    </span>
  

  <div class="article-inner">
    
    <div class="article-content article-content-cloud" itemprop="articleBody">
      
        
        <h2 id="概述类的加载器及类加载过程"><a href="#概述类的加载器及类加载过程" class="headerlink" title="概述类的加载器及类加载过程"></a>概述类的加载器及类加载过程</h2><ul>
<li>类的加载过程一： Loading 加载</li>
<li>类的加载过程二： Linking 链接<ul>
<li>Verification 验证</li>
<li>Preparation 准备</li>
<li>Resolution 解析</li>
</ul>
</li>
<li>类的加载过程三： Initialization 初始化</li>
</ul>
<a id="more"></a>

<h3 id="概述类的加载器"><a href="#概述类的加载器" class="headerlink" title="概述类的加载器"></a>概述类的加载器</h3><p><img src="/2020/07/03/JVM-01/JVM.png" alt="JVM"></p>
<p>Java环境： Java 8</p>
<h4 id="类加载器子系统作用"><a href="#类加载器子系统作用" class="headerlink" title="类加载器子系统作用"></a>类加载器子系统作用</h4><ul>
<li>类加载器子系统负责从文件系统或者网络中加载Class文件，class文件在文件开头有特定的文件标识。</li>
<li>ClassLoader只负责class文件的加载，至于它是否可以运行，则由Execution Engine决定。</li>
<li>加载的类信息存放于一块称为方法区的内存空间。除了类的信息外，方法区中还会存放运行时常量池信息，可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)</li>
</ul>
<h4 id="类加载器ClassLoader角色"><a href="#类加载器ClassLoader角色" class="headerlink" title="类加载器ClassLoader角色"></a>类加载器ClassLoader角色</h4><ol>
<li>class file 存在于本地硬盘上，可以理解为设计师画在纸上的模板，而最终这个模板在执行的时候是要加载到JVM当中来根据这个文件实例化出n个一模一样的实例。</li>
<li>class file 加载到JVM中,被称为DNA元数据模板,放在方法区。</li>
<li>在.class文件-&gt; JVM -&gt;最终成为元数据模板,此过程就要一个运输工具(类装载器Class Loader) ,扮演一个快递员的角色。</li>
</ol>
<h3 id="类的加载过程"><a href="#类的加载过程" class="headerlink" title="类的加载过程"></a>类的加载过程</h3><ul>
<li>Loading 加载</li>
<li>Linking 链接<ul>
<li>Verification 验证</li>
<li>Preparation 准备</li>
<li>Resolution 解析</li>
</ul>
</li>
<li>Initialization 初始化</li>
</ul>
<h4 id="加载"><a href="#加载" class="headerlink" title="加载"></a>加载</h4><ol>
<li>通过一个类的全限定名获取定义此类的二进制字节流</li>
<li>将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构</li>
<li>在内存中生成一个代表这个类的java.lang.Class对象，作为方法区这个类的各种数据的访问入口</li>
</ol>
<p>补充:加载.class 文件的方式</p>
<ul>
<li>从本地系统中直接加载</li>
<li>通过网络获取，典型场景: Web Applet</li>
<li>从zip压缩包中读取，成为日后jar、war格式的基础</li>
<li>运行时计算生成，使用最多的是:动态代理技术</li>
<li>由其他文件生成，典型场景: JSP应用</li>
<li>从专有数据库中提取.class文件，比较少见</li>
<li>从加密文件中获取，典型的防Class文件被反编译的保护措施</li>
</ul>
<h4 id="链接"><a href="#链接" class="headerlink" title="链接"></a>链接</h4><p>验证(Verify) :</p>
<ul>
<li>目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求，保证被加载类的正确性，不会危害虚拟机自身安全。</li>
<li>主要包括四种验证，文件格式验证，元数据验证，字节码验证，符号引用验证。</li>
</ul>
<p>准备(Prepare) :</p>
<ul>
<li>为类变量分配内存并且设置该类变量的默认初始值，即零值。</li>
<li>这里不包含用final修饰的static,因为final在编译的时候就会分配了，准备阶段会显式初始化;</li>
<li>这里不会为实例变量分配初始化，类变量会分配在方法区中，而实例变量是会随着对象一起分配到Java堆中。</li>
</ul>
<p>解析(Resolve) :</p>
<ul>
<li>将常量池内的符号引用转换为直接引用的过程。</li>
<li>事实上，解析操作往往会伴随着JVM在执行完初始化之后再执行。</li>
<li>符号引用就是一组符号来描述所引用的目标。符号引用的字面量形式明确定义在《java虚拟机规范》的Class文件格式中。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。</li>
<li>解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的 CONSTANT_Class_info、 CONSTANT_Fieldref_info、 CONSTANT_Methodref_info等 。</li>
</ul>
<h4 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h4><ul>
<li><strong>初始化阶段就是执行类构造器方法&lt;clinit&gt;()的过程。</strong></li>
<li>此方法不需定义，是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。</li>
<li>构造器方法中指令按语句在源文件中出现的顺序执行。</li>
<li><strong>&lt;clinit&gt;()不同于类的构造器。(关联:构造器是虚拟机视角下的&lt;init&gt;())</strong></li>
<li>若该类具有父类，JVM会保证子类的&lt;clinit&gt;()执行前，父类的&lt;clinit&gt;()已经执行完毕。</li>
<li>虚拟机必须保证一个类的&lt;clinit&gt;()方法在多线程下被同步加锁。</li>
</ul>
<hr>
<h4 id="相关代码"><a href="#相关代码" class="headerlink" title="相关代码"></a>相关代码</h4><p>ClassInitTest.java</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClassInitTest</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> num = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        num = <span class="number">2</span>;</span><br><span class="line">        number = <span class="number">20</span>;</span><br><span class="line">        <span class="comment">// System.out.println(num); //不会报错</span></span><br><span class="line">        <span class="comment">// System.out.println(number);// 报错，非法的前向引用 Illegal forward reference</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> number = <span class="number">10</span>; <span class="comment">//linking之prepare: number = 0 --&gt; initial: 20 --&gt; 10</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(ClassInitTest.num);<span class="comment">//2</span></span><br><span class="line">        System.out.println(ClassInitTest.number);<span class="comment">//10</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>ClassInitTest.class</p>
<p>字节码文件：Method - &lt;clinit&gt; -  code</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> <span class="number">0</span> iconst_1</span><br><span class="line"> 1 putstatic #3 &lt;com/example/java/ClassInitTest.num&gt;</span><br><span class="line"> <span class="number">4</span> iconst_2</span><br><span class="line"> 5 putstatic #3 &lt;com/example/java/ClassInitTest.num&gt;</span><br><span class="line"> <span class="number">8</span> bipush <span class="number">20</span></span><br><span class="line">10 putstatic #5 &lt;com/example/java/ClassInitTest.number&gt;</span><br><span class="line"><span class="number">13</span> bipush <span class="number">10</span></span><br><span class="line">15 putstatic #5 &lt;com/example/java/ClassInitTest.number&gt;</span><br><span class="line"><span class="number">18</span> <span class="keyword">return</span></span><br></pre></td></tr></table></figure></div>

<hr>
<p>ClinitTest.java</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClinitTest</span> </span>&#123;</span><br><span class="line">    <span class="comment">//任何一个类声明以后，内部至少存在一个类的构造器</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> a = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> c = <span class="number">3</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> b = <span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ClinitTest</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        a = <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">int</span> d = <span class="number">20</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>ClinitTest.class</p>
<p>字节码文件：Method - &lt;clinit&gt; -  code</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> iconst_3</span><br><span class="line">1 putstatic #3 &lt;com/example/java/ClinitTest.c&gt;</span><br><span class="line"><span class="number">4</span> <span class="keyword">return</span></span><br></pre></td></tr></table></figure></div>

<p>字节码文件：Method - &lt;init&gt; -  code</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0</span> aload_0</span><br><span class="line"> 1 invokespecial #1 &lt;java/lang/Object.&lt;init&gt;&gt;</span><br><span class="line"> <span class="number">4</span> aload_0</span><br><span class="line"> <span class="number">5</span> iconst_1</span><br><span class="line"> 6 putfield #2 &lt;com/example/java/ClinitTest.a&gt;</span><br><span class="line"> <span class="number">9</span> aload_0</span><br><span class="line"><span class="number">10</span> bipush <span class="number">10</span></span><br><span class="line">12 putfield #2 &lt;com/example/java/ClinitTest.a&gt;</span><br><span class="line"><span class="number">15</span> bipush <span class="number">20</span></span><br><span class="line"><span class="number">17</span> istore_1</span><br><span class="line"><span class="number">18</span> <span class="keyword">return</span></span><br></pre></td></tr></table></figure></div>

<hr>
<p>多线程，验证 &lt;clinit&gt;() 方法被同步加锁：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DeadThreadTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Runnable r = () -&gt; &#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">"开始"</span>);</span><br><span class="line">            DeadThread dead = <span class="keyword">new</span> DeadThread();</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">"结束"</span>);</span><br><span class="line">        &#125;;</span><br><span class="line">        Thread t1 = <span class="keyword">new</span> Thread(r, <span class="string">"线程1 "</span>);</span><br><span class="line">        Thread t2 = <span class="keyword">new</span> Thread(r, <span class="string">"线程2 "</span>);</span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DeadThread</span> </span>&#123;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">"初始化当前类"</span>);</span><br><span class="line">            <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>程序输出：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">线程1 开始</span><br><span class="line">线程2 开始</span><br><span class="line">线程1 初始化当前类</span><br><span class="line"></span><br><span class="line">Process finished with <span class="built_in">exit</span> code 130 (interrupted by signal 2: SIGINT)</span><br></pre></td></tr></table></figure></div>

<p>或者是</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">线程2 开始</span><br><span class="line">线程1 开始</span><br><span class="line">线程2 初始化当前类</span><br><span class="line"></span><br><span class="line">Process finished with <span class="built_in">exit</span> code 130 (interrupted by signal 2: SIGINT)</span><br></pre></td></tr></table></figure></div>

<hr>
<h3 id="类加载器的分类"><a href="#类加载器的分类" class="headerlink" title="类加载器的分类"></a>类加载器的分类</h3><ul>
<li>JVM支持两种类型的类加载器，分别为<strong>引导类加载器 (Bootstrap ClassLoader)</strong> 和<strong>自定义类加载器(User-Defined ClassLoader)</strong> 。</li>
<li>从概念上来讲，自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器，但是Java虚拟机规范却没有这么定义，而是<strong>将所有派生于抽象类 <code>ClassLoader</code> 的类加载器都划分为自定义类加载器。</strong></li>
<li>无论类加载器的类型如何划分，在程序中我们最常见的类加载器始终只有3个，如下所示:<ul>
<li>Bootstrap Class Loader</li>
<li>Extension Class Loader</li>
<li>System Class Loader</li>
<li>User Defined Class Loader</li>
</ul>
</li>
</ul>
<p>这里的四者之间的关系是包含关系。不是上层下层，也不是子父类的继承关系。</p>
<hr>
<p>ClassLoaderTest.java</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClassLoaderTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//获取系统类加载器</span></span><br><span class="line">        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();</span><br><span class="line">        System.out.println(systemClassLoader);<span class="comment">//sun.misc.Launcher$AppClassLoader@18b4aac2</span></span><br><span class="line">        <span class="comment">//获取其上层: 扩展类加载器</span></span><br><span class="line">        ClassLoader extClassLoader = systemClassLoader.getParent();</span><br><span class="line">        System.out.println(extClassLoader);<span class="comment">//sun.misc.Launcher$ExtClassLoader@1540e19d</span></span><br><span class="line">        <span class="comment">//获取其上层: 获取不到引导类加载器</span></span><br><span class="line">        ClassLoader bootstrapClassLoader = extClassLoader.getParent();</span><br><span class="line">        System.out.println(bootstrapClassLoader);<span class="comment">//null</span></span><br><span class="line">        <span class="comment">//对于用户自定义类来说: 默认使用系统类加载器进行加载</span></span><br><span class="line">        ClassLoader classLoader = ClassLoaderTest<span class="class">.<span class="keyword">class</span>.<span class="title">getClassLoader</span>()</span>;</span><br><span class="line">        System.out.println(classLoader);<span class="comment">//sun.misc.Launcher$AppClassLoader@18b4aac2</span></span><br><span class="line">        <span class="comment">//String类使用引导类加载器进行加载的。---&gt; Java的核心类库都是使用引导类加载器进行加载的。</span></span><br><span class="line">        ClassLoader classLoader1 = String<span class="class">.<span class="keyword">class</span>.<span class="title">getClassLoader</span>()</span>;</span><br><span class="line">        System.out.println(classLoader1);<span class="comment">//null</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">sun.misc.Launcher$AppClassLoader@<span class="number">18</span>b4aac2</span><br><span class="line">sun.misc.Launcher$ExtClassLoader@<span class="number">61</span>bbe9ba</span><br><span class="line"><span class="keyword">null</span></span><br><span class="line">sun.misc.Launcher$AppClassLoader@<span class="number">18</span>b4aac2</span><br><span class="line"><span class="keyword">null</span></span><br><span class="line"></span><br><span class="line">Process finished with exit code <span class="number">0</span></span><br></pre></td></tr></table></figure></div>

<hr>
<h4 id="虚拟机自带的加载器"><a href="#虚拟机自带的加载器" class="headerlink" title="虚拟机自带的加载器"></a>虚拟机自带的加载器</h4><p>启动类加载器(引导类加载器，Bootstrap ClassLoader)</p>
<ul>
<li>➢ 这个类加载使用C&#x2F;C++语言实现的，嵌套在JVM内部。</li>
<li>➢ 它用来加载Java的核心库( <code>JAVA_ HOME/jre/lib/rt.jar</code> 、<code>resources.jar</code> 或 <code>sun.boot.class.path</code> 路径下的内容) , 用于提供JVM自身需要的类</li>
<li>➢ 并不继承自 <code>java.lang.ClassLoader</code> ,没有父加载器。</li>
<li>➢ 加载扩展类和应用程序类加载器，并指定为他们的父类加载器。</li>
<li>➢ 出于安全考虑，Bootstrap启动类加载器只加载包名为 <code>java、javax、sun</code> 等开头的类</li>
</ul>
<p>扩展类加载器(Extension ClassLoader)</p>
<ul>
<li>➢ <strong>Java语言编写</strong>，由 <code>sun.misc.Launcher$ExtClassLoader</code> 实现。</li>
<li>➢ <strong>派生于 <code>ClassLoader</code> 类</strong></li>
<li>➢ 父类加载器为启动类加载器</li>
<li>➢ 从 <code>java.ext.dirs</code> 系统属性所指定的目录中加载类库，或从JDK的安装目录的 <code>jre/lib/ext</code> 子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下，也会自动由扩展类加载器加载。</li>
</ul>
<p>应用程序类加载器(系统类加载器，AppClassLoader)</p>
<ul>
<li>➢ java语言编写，由 <code>sun.misc.Launcher$AppClassLoader</code> 实现</li>
<li>➢ 派生于 <code>ClassLoader</code> 类</li>
<li>➢ 父类加载器为扩展类加载器</li>
<li>➢ 它负责加载环境变量classpath或系统属性 <code>java.class.path</code> 指定路径下的类库</li>
<li>➢ <strong>该类加载是程序中默认的类加载器</strong>，一般来说，Java应用的类都是由它来完成加载</li>
<li>➢ 通过 <code>ClassLoader#getSystemClassLoader()</code> 方法可以获取到该类加载器</li>
</ul>
<hr>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.net.URL;</span><br><span class="line"><span class="keyword">import</span> java.security.Provider;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClassLoaderTest1</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"******启动类加載器*******"</span>);</span><br><span class="line">        <span class="comment">//荻取BootstrapClassLoader能够加栽的api的路径</span></span><br><span class="line">        URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();</span><br><span class="line">        <span class="keyword">for</span> (URL element : urLs) &#123;</span><br><span class="line">            System.out.println(element.toExternalForm());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//从上面的路径中随意选择一个美, 来看看他的类加載器是什么:</span></span><br><span class="line">        ClassLoader classLoader = Provider<span class="class">.<span class="keyword">class</span>.<span class="title">getClassLoader</span>()</span>;</span><br><span class="line">        System.out.println(classLoader); <span class="comment">// null</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">"******扩展类加載器******"</span>);</span><br><span class="line">        String extDirs = System.getProperty(<span class="string">"java.ext.dirs"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// macOS下环境变量的分隔符是:</span></span><br><span class="line">        <span class="comment">// Windows下分隔符是;</span></span><br><span class="line">        <span class="keyword">for</span> (String path : extDirs.split(<span class="string">":"</span>)) &#123;</span><br><span class="line">            System.out.println(path);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//从上面的路径中随意选择一个类，来看看他的类加载器是什么:扩展类加载器</span></span><br><span class="line">        ClassLoader classLoader1 = CurveDB<span class="class">.<span class="keyword">class</span>.<span class="title">getClassLoader</span>()</span>;</span><br><span class="line">        System.out.println(classLoader1);<span class="comment">//sun.misc.Launcher$ExtClassLoader@1540e19d</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">******启动类加載器*******</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/resources.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/rt.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/sunrsasign.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jsse.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jce.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/charsets.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfr.jar</span><br><span class="line">file:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/classes</span><br><span class="line">null</span><br><span class="line">******扩展类加載器******</span><br><span class="line">/Users/yan/Library/Java/Extensions</span><br><span class="line">/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext</span><br><span class="line">/Library/Java/Extensions</span><br><span class="line">/Network/Library/Java/Extensions</span><br><span class="line">/System/Library/Java/Extensions</span><br><span class="line">/usr/lib/java</span><br><span class="line">sun.misc.Launcher<span class="variable">$ExtClassLoader</span>@355da254</span><br><span class="line"></span><br><span class="line">Process finished with <span class="built_in">exit</span> code 0</span><br></pre></td></tr></table></figure></div>

<hr>
<h4 id="用户自定义类加载器"><a href="#用户自定义类加载器" class="headerlink" title="用户自定义类加载器"></a>用户自定义类加载器</h4><ul>
<li>在Java的日常应用程序开发中，类的加载几乎是由上述3种类加载器相互配合执行的，在必要时，我们还可以自定义类加载器，来定制类的加载方式。</li>
<li>为什么要自定义类加载器?<ul>
<li>➢ 隔离加载类</li>
<li>➢ 修改类加载的方式</li>
<li>➢ 扩展加载源</li>
<li>➢ 防止源码泄漏</li>
</ul>
</li>
</ul>
<p>用户自定义类加载器实现步骤:</p>
<ol>
<li>开发人员可以通过继承抽象类 <code>java.lang.ClassLoader</code> 类的方式，实现自己的类加载器，以满足一些特殊的需求</li>
<li>在JDK1.2之前，在自定义类加载器时，总会去继承 <code>ClassLoader</code> 类并重写 <code>loadClass()</code> 方法，从而实现自定义的类加载类，但是在JDK1.2之后已不再建议用户去覆盖 <code>loadClass()</code> 方法，而是建议把自定义的类加载逻辑写在 <code>findClass()</code> 方法中</li>
<li>在编写自定义类加载器时，如果没有太过于复杂的需求，可以直接继承 <code>URLClassLoader</code> 类，这样就可以避免自己去编写 <code>findClass()</code> 方法及其获取字节码流的方式，使自定义类加载器编写更加简洁。</li>
</ol>
<hr>
<p>手写自定义类加载器：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.java;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.FileNotFoundException;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CustomClassLoader</span> <span class="keyword">extends</span> <span class="title">ClassLoader</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> Class&lt;?&gt; findClass(String name) <span class="keyword">throws</span> ClassNotFoundException &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">byte</span>[] result = getClassFromCustomPath(name);</span><br><span class="line">            <span class="keyword">if</span> (result == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> FileNotFoundException();</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> defineClass(name, result, <span class="number">0</span>, result.length); <span class="comment">//</span></span><br><span class="line">                <span class="comment">// findClass和defineClass配合使用</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (FileNotFoundException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ClassNotFoundException(name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">byte</span>[] getClassFromCustomPath(String name) &#123;</span><br><span class="line">        <span class="comment">//从自定义路径中加载指定类:细节略</span></span><br><span class="line">        <span class="comment">//如果指定路径的字节码文件进行了加密，则需要在此方法中进行解密操作。</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<hr>
<p>ClassLoader类， 它是一个抽象类，其后所有的类加载器都继承自 ClassLoader (不包括启动类加载器)</p>
<blockquote>
<table>
<thead>
<tr>
<th>方法名称</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>getParent()</td>
<td>返回该类加载器的超类加载器</td>
</tr>
<tr>
<td>loadClass(String name)</td>
<td>加载名称为name的类，返回结果为 <code>java.lang.Class</code> 类的实例</td>
</tr>
<tr>
<td>findClass(String name)</td>
<td>查找名称为name的类，返回结果为 <code>java.lang.Class</code> 类的实例</td>
</tr>
<tr>
<td>findLoadedClass(String name)</td>
<td>查找名称为name的已经被加载过的类，返回结果为 <code>java.lang.Class</code> 类的实例</td>
</tr>
<tr>
<td>defineClass(String name, byte[] b, int off, int len)</td>
<td>把字节数组b中的内容转换为一个Java类，返回结果为 <code>java.lang.Class</code> 类的实例</td>
</tr>
<tr>
<td>resolveClass(Class&lt;?&gt; c)</td>
<td>连接指定的一个Java类</td>
</tr>
</tbody></table>
</blockquote>
<p>获取ClassLoader的途径</p>
<table>
<thead>
<tr>
<th>方式</th>
<th>方法</th>
</tr>
</thead>
<tbody><tr>
<td>方式一: 获取当前类的ClassLoader</td>
<td>clazz.getClassLoader()</td>
</tr>
<tr>
<td>方式二: 获取当前线程上下文的ClassLoader</td>
<td>Thread.currentThread().getContextClassLoader()</td>
</tr>
<tr>
<td>方式三: 获取系统的ClassLoader</td>
<td>ClassLoader.getSystemClassLoader()</td>
</tr>
<tr>
<td>方式四: 获取调用者的ClassLoader</td>
<td>DriverManager.getCallerClassLoader()</td>
</tr>
</tbody></table>
<h4 id="🌿-双亲委派机制"><a href="#🌿-双亲委派机制" class="headerlink" title="🌿 双亲委派机制"></a>🌿 双亲委派机制</h4><p>Java虚拟机对class文件采用的是<strong>按需加载</strong>的方式，也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时，Java虛拟机采用的是<strong>双亲委派模式</strong>，即把请求交由父类处理，它是一种任务委派模式。</p>
<p>● 工作原理</p>
<ol>
<li>如果一个类加载器收到了类加载请求，它并不会自己先去加载，而是把这个请求委托给父类的加载器去执行;</li>
<li>如果父类加载器还存在其父类加载器，则进一步向上委托，依次递归，请求最终将到达项层的启动类加载器;</li>
<li>如果父类加载器可以完成类加载任务，就成功返回，倘若父类加载器无法完成此加载任务，子加载器才会尝试自己去加载，这就是双亲委派模式。</li>
</ol>
<hr>
<p>双亲委派机制举例：自己手写一个String类放在自建的java.lang包下：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> java.lang;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">String</span> </span>&#123;</span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">"我是自定义的String类的静态代码块"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"hello,String"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行，输出：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="false"data-rel="JAVA"><figure class="iseeu highlight /java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span></span><br><span class="line"><span class="function">否则 JavaFX 应用程序类必须扩展javafx.application.Application</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">Process finished with exit code 1</span></span><br></pre></td></tr></table></figure></div>

<p><em>为什么有以上输出？</em></p>
<p>由于双亲委派机制，我们自定义的 <code>java.lang.String</code> 类并不是由系统类加载器加载的，而是向上委托给了扩展类加载器又接着向上委托给了启动类加载器进行加载，而启动类加载器加载的是java核心API中的 <code>java.lang.String</code> 类而不是我们自定义的 <code>java.lang.String</code> 类，其中并没有main方法。</p>
<hr>
<p>双亲委派机制举例2</p>
<p>rt.jar SPI（Service Provider Interface）核心类<br>jdbc.jar SPI接口实现类</p>
<p>rt.jar中的SPI接口调用接口实现类中的方法：</p>
<ul>
<li>SPI接口是由引导类加载器（BootstrapClassLoader）加载的</li>
<li>SPI接口实现类是由线程上下文加载器（ContextClassLoader）加载的，而线程上下文加载器默认为系统类加载器（AppClassLoader）加载的</li>
</ul>
<hr>
<p>● 双亲委派机制 优势</p>
<ul>
<li>➢ 避免类的重复加载 （两个必要条件）</li>
<li>➢ 保护程序安全，防止核心API被随意篡改<ul>
<li>自定义类: java.lang.String</li>
<li>自定义类: java.lang.ShkStart<ul>
<li>java.lang.SecurityException: Prohibited package name; java.lang</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>● 在JVM中 表示两个class对象是否为同一个类存在两个必要条件:</p>
<ul>
<li>➢ 类的完整类名必须一致，包括包名。</li>
<li>➢ 加载这个类的ClassLoader (指ClassLoader实例对象)必须相同。</li>
</ul>
<p>换句话说，在JVM中，即使这两个类对象(class对象)来源同一个Class文件，被同一个虚拟机所加载，但只要加载它们的ClassLoader实例对象不同，那么这两个类对象也是不相等的。</p>
<p>自定义String类，但是在加载自定义String类的时候会率先使用引导类加载器加载，而引导类加载器在加载的过程中会先加载jdk自带的文件(rt.jar包中java\lang\String.class)，报错信息说没有main方法，就是因为加载的是rt.jar包中的String类。这样可以保证对java核心源代码的保护，这就是<strong>沙箱安全机制</strong>。</p>
<hr>
<h3 id="对类加载器的引用、类的主动使用和被动使用"><a href="#对类加载器的引用、类的主动使用和被动使用" class="headerlink" title="对类加载器的引用、类的主动使用和被动使用"></a>对类加载器的引用、类的主动使用和被动使用</h3><p>对类加载器的引用：</p>
<p>JVM必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是由用户类加载器加载的，那么JVM会<strong>将这个类加载器的一个引用作为类型信息的一部分保存在方法区中</strong>。当解析一个类型到另一个类型的引用的时候，JVM需要保证这两个类型的类加载器是相同的。</p>
<p>类的主动使用和被动使用：</p>
<p><strong>Java程序对类的使用方式分为: 主动使用和被动使用。</strong><br>● 主动使用，又分为七种情况:</p>
<ul>
<li>➢ 创建类的实例</li>
<li>➢ 访问某个类或接口的静态变量，或者对该静态变量赋值</li>
<li>➢ 调用类的静态方法</li>
<li>➢ 反射(比如: <code>Class.forName(&quot;com.atguigu.Test&quot;)</code> )</li>
<li>➢ 初始化一个类的子类</li>
<li>➢ Java虚拟机启动时被标明为启动类的类</li>
<li>➢ JDK 7开始提供的动态语言支持:<ul>
<li><code>java.lang.invoke.MethodHandle</code> 实例的解析结果</li>
<li><code>REF_getStatic</code>、 <code>REF_putStatic</code>、 <code>REF_invokeStatic</code> 句柄对应的类没有初始化，则初始化</li>
</ul>
</li>
</ul>
<p>● 除了以上七种情况，其他使用Java类的方式都被看作是<strong>对类的被动使用，都不会导致类的初始化</strong>。</p>

          
      
    </div>
    
    
      <footer class="article-footer">
        完
      </footer>
    
  </div>
  
    
<nav id="article-nav">
  <div class="article-nav-block">
    
      <a href="../../05/JVM-02/" id="article-nav-newer" class="article-nav-link-wrap">
        <strong class="article-nav-caption"></strong>
        <div class="article-nav-title">
          
            JVM 02 运行时数据区概述及线程、程序计数器
          
        </div>
      </a>
    
  </div>
  <div class="article-nav-block">
    
      <a href="../../../06/30/mapreduce-error-version-of-the-Java-Runtime-only-recognizes-class-file-versions-up-to-52/" id="article-nav-older" class="article-nav-link-wrap">
        <div class="article-nav-title">Hadoop Mapreduce作业执行过程中报错 this version of the Java Runtime only recognizes class file versions up to 52.0</div>
        <strong class="article-nav-caption"></strong>
      </a>
    
  </div>
</nav>

    <!-- <link rel="stylesheet" href="/css/gitment.css">  -->
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>

<div id="vcommentsContainer"></div>
<!--引用评论框输入特效js文件-->

<script src="../../../../js/shuru.js"></script>

<script>
  POWERMODE.colorful = true; // make power mode colorful
  POWERMODE.shake = true; // turn off shake
  document.body.addEventListener('input', POWERMODE);
</script>
<!-- valine评论系统 -->
<script>
  new Valine({
      el: '#vcommentsContainer',
      appId: 'AttjBiS7UwxkxjV1CSrNywoi-gzGzoHsz',
      appKey: 'F50aWycFFmAPLC8CfSW7rXdP',
      avatar: 'monsterid',
      enableQQ: true,
      placeholder: '昵称处填QQ号自动抓取网名和邮箱哟~'
  })
</script>


    <!-- <link rel="stylesheet" href="/css/gitment.css"> 
<script src="/js/gitment.js"></script>

<div id="gitmentContainer"></div>

<script>
var gitment = new Gitment({
  owner: '',
  repo: '',
  oauth: {
    client_id: '',
    client_secret: '',
  },
})
gitment.render('gitmentContainer')
</script>

 -->

  
  
</article>
</section>
        <aside id="sidebar">
  
    <div class="widget-box">
  <div class="avatar-box">
    <img class="avatar" src="https://q1.qlogo.cn/g?b=qq&amp;nk=979727728&amp;s=640" title="图片来自QQ"></img>
    <h3 class="avatar-name">
      
        许嵩老公
      
    </h3>
    <p class="avatar-slogan">
      深吸一口梦，吹个气球存起来。
    </p>
  </div>
</div>


  
    

  
    
  <div class="widget-box">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/NET/" rel="tag">.NET</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Cookie/" rel="tag">Cookie</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/ES6/" rel="tag">ES6</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Git-Bash/" rel="tag">Git Bash</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Github/" rel="tag">Github</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Github-Actions/" rel="tag">Github Actions</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/HDFS/" rel="tag">HDFS</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/HTTP/" rel="tag">HTTP</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Hadoop/" rel="tag">Hadoop</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Hexo/" rel="tag">Hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Idea/" rel="tag">Idea</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/JVM/" rel="tag">JVM</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Java/" rel="tag">Java</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/JavaScript/" rel="tag">JavaScript</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Linux/" rel="tag">Linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/MapReduce/" rel="tag">MapReduce</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Markdown/" rel="tag">Markdown</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Maven/" rel="tag">Maven</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Node/" rel="tag">Node</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Node-js/" rel="tag">Node.js</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/SQL/" rel="tag">SQL</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Serial-Port/" rel="tag">Serial Port</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Shell/" rel="tag">Shell</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/SpringBoot/" rel="tag">SpringBoot</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/TCP/" rel="tag">TCP</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/VSCode/" rel="tag">VSCode</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/Vue/" rel="tag">Vue</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/WebSocket/" rel="tag">WebSocket</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/YARN/" rel="tag">YARN</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/hexo/" rel="tag">hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/macOS/" rel="tag">macOS</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/ssh/" rel="tag">ssh</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/" rel="tag">中文乱码</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/" rel="tag">大数据</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/" rel="tag">安装教程</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%AF%86%E9%92%A5/" rel="tag">密钥</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E5%B9%B6%E8%A1%8C%E7%BC%96%E7%A8%8B/" rel="tag">并行编程</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" rel="tag">数据库</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E7%94%B5%E8%84%91/" rel="tag">电脑</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E7%AB%B9%E4%BA%91/" rel="tag">竹云</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E7%BB%88%E7%AB%AF/" rel="tag">终端</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E8%84%9A%E6%9C%AC/" rel="tag">脚本</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E8%BD%AC%E8%BD%BD/" rel="tag">转载</a></li><li class="tag-list-item"><a class="tag-list-link" href="../../../../tags/%E8%BD%AF%E4%BB%B6/" rel="tag">软件</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-box">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="../../../../tags/NET/" style="font-size: 10px;">.NET</a> <a href="../../../../tags/Cookie/" style="font-size: 10px;">Cookie</a> <a href="../../../../tags/ES6/" style="font-size: 10px;">ES6</a> <a href="../../../../tags/Git-Bash/" style="font-size: 11.67px;">Git Bash</a> <a href="../../../../tags/Github/" style="font-size: 13.33px;">Github</a> <a href="../../../../tags/Github-Actions/" style="font-size: 10px;">Github Actions</a> <a href="../../../../tags/HDFS/" style="font-size: 10px;">HDFS</a> <a href="../../../../tags/HTTP/" style="font-size: 11.67px;">HTTP</a> <a href="../../../../tags/Hadoop/" style="font-size: 18.33px;">Hadoop</a> <a href="../../../../tags/Hexo/" style="font-size: 10px;">Hexo</a> <a href="../../../../tags/Idea/" style="font-size: 10px;">Idea</a> <a href="../../../../tags/JVM/" style="font-size: 18.33px;">JVM</a> <a href="../../../../tags/Java/" style="font-size: 20px;">Java</a> <a href="../../../../tags/JavaScript/" style="font-size: 16.67px;">JavaScript</a> <a href="../../../../tags/Linux/" style="font-size: 15px;">Linux</a> <a href="../../../../tags/MapReduce/" style="font-size: 11.67px;">MapReduce</a> <a href="../../../../tags/Markdown/" style="font-size: 10px;">Markdown</a> <a href="../../../../tags/Maven/" style="font-size: 13.33px;">Maven</a> <a href="../../../../tags/Node/" style="font-size: 10px;">Node</a> <a href="../../../../tags/Node-js/" style="font-size: 10px;">Node.js</a> <a href="../../../../tags/SQL/" style="font-size: 13.33px;">SQL</a> <a href="../../../../tags/Serial-Port/" style="font-size: 10px;">Serial Port</a> <a href="../../../../tags/Shell/" style="font-size: 11.67px;">Shell</a> <a href="../../../../tags/SpringBoot/" style="font-size: 10px;">SpringBoot</a> <a href="../../../../tags/TCP/" style="font-size: 10px;">TCP</a> <a href="../../../../tags/VSCode/" style="font-size: 10px;">VSCode</a> <a href="../../../../tags/Vue/" style="font-size: 10px;">Vue</a> <a href="../../../../tags/WebSocket/" style="font-size: 11.67px;">WebSocket</a> <a href="../../../../tags/YARN/" style="font-size: 10px;">YARN</a> <a href="../../../../tags/hexo/" style="font-size: 11.67px;">hexo</a> <a href="../../../../tags/macOS/" style="font-size: 11.67px;">macOS</a> <a href="../../../../tags/ssh/" style="font-size: 11.67px;">ssh</a> <a href="../../../../tags/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/" style="font-size: 10px;">中文乱码</a> <a href="../../../../tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/" style="font-size: 10px;">大数据</a> <a href="../../../../tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/" style="font-size: 10px;">安装教程</a> <a href="../../../../tags/%E5%AF%86%E9%92%A5/" style="font-size: 10px;">密钥</a> <a href="../../../../tags/%E5%B9%B6%E8%A1%8C%E7%BC%96%E7%A8%8B/" style="font-size: 10px;">并行编程</a> <a href="../../../../tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" style="font-size: 10px;">数据库</a> <a href="../../../../tags/%E7%94%B5%E8%84%91/" style="font-size: 11.67px;">电脑</a> <a href="../../../../tags/%E7%AB%B9%E4%BA%91/" style="font-size: 11.67px;">竹云</a> <a href="../../../../tags/%E7%BB%88%E7%AB%AF/" style="font-size: 13.33px;">终端</a> <a href="../../../../tags/%E8%84%9A%E6%9C%AC/" style="font-size: 10px;">脚本</a> <a href="../../../../tags/%E8%BD%AC%E8%BD%BD/" style="font-size: 10px;">转载</a> <a href="../../../../tags/%E8%BD%AF%E4%BB%B6/" style="font-size: 10px;">软件</a>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2023/02/">二月 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2023/01/">一月 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2022/11/">十一月 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2022/09/">九月 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2022/08/">八月 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2021/12/">十二月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2021/02/">二月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2021/01/">一月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2020/08/">八月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2020/07/">七月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="../../../../archives/2020/06/">六月 2020</a></li></ul>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="../../../../2023/02/13/%E4%BD%BF%E7%94%A8Node-js%E5%90%8E%E5%8F%B0%E8%AF%BB%E5%8F%96%E4%B8%B2%E5%8F%A3%E6%95%B0%E6%8D%AE%E5%B9%B6%E9%80%9A%E8%BF%87WebSocket%E5%AE%9E%E6%97%B6%E6%98%BE%E7%A4%BA%E5%9C%A8%E7%BD%91%E9%A1%B5%E4%B8%8A/">使用Node.js后台读取串口数据并通过WebSocket实时显示在网页上</a>
          </li>
        
          <li>
            <a href="../../../../2023/02/09/%E4%BD%9C%E4%B8%BA%E7%94%A8%E6%88%B7%EF%BC%8C%E4%BF%AE%E6%94%B9Cookie%E6%9C%89%E6%95%88%E6%9C%9F%EF%BC%8C%E5%BB%B6%E9%95%BFCookie%E6%9C%9F%E9%99%90/">作为用户，修改Cookie有效期，延长Cookie期限</a>
          </li>
        
          <li>
            <a href="../../../../2023/02/08/%E7%BB%88%E7%AB%AF%E5%91%BD%E4%BB%A4%E4%BB%A3%E7%90%86/">终端命令网络设置</a>
          </li>
        
          <li>
            <a href="../../../../2023/01/18/Windows%E7%B3%BB%E7%BB%9FC%E7%9B%98%E6%B8%85%E7%90%86%E5%B7%A5%E5%85%B7FreeMove%E5%8F%8A%E6%96%87%E4%BB%B6%E5%8D%A0%E7%94%A8%E8%BF%9B%E7%A8%8B%E6%9F%A5%E7%9C%8B%E8%BD%AF%E4%BB%B6LockHunter%E9%85%8D%E5%90%88%E4%BD%BF%E7%94%A8/">Windows系统C盘清理工具FreeMove及文件占用进程查看软件LockHunter配合使用</a>
          </li>
        
          <li>
            <a href="../../../../2023/01/14/AutoReconnectWiFi/">检测断网自动重连WiFi脚本</a>
          </li>
        
      </ul>
    </div>
  </div>

  
      <div class="widget-box">
    <h3 class="widget-title">友链</h3>
    <div class="widget">
      
        <!-- <a style="display: block;" href="../../../../https:/xiaoyan94.github.io/" title target='_blank' -->
        <a style="display: block;" href="https://xiaoyan94.github.io/" title target='_blank'
        >Github Pages</a>
      
        <!-- <a style="display: block;" href="../../../../https:/xy94.gitee.io/" title target='_blank' -->
        <a style="display: block;" href="https://xy94.gitee.io/" title target='_blank'
        >Gitee Pages</a>
      
    </div>
  </div>

  
 
  
</aside>
      </div>
      <footer id="footer">
  <div class="foot-box global-width center">
    &copy; 2023 许嵩老公 &nbsp;&nbsp;
    Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    &nbsp;|&nbsp;主题 <a href="https://github.com/yiluyanxia/hexo-theme-antiquity" target="_blank" rel="noopener">antiquity</a>
    <br>
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">不蒜子告之   阁下是第<span id="busuanzi_value_site_pv"></span>个访客</span>
    
  </div>
  
  <!--引入文字点击特效-->
  <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
  
<script src="../../../../js/dianji.js"></script>

</footer>

<!--添加回到顶部按钮-->
<style>
/* 小猫置顶 */
/* 自定义回到顶部样式 */
.cd-top {
  position: fixed;
  right: 25px;
  top: -900px;
  z-index: 99;
  width: 70px;
  height: 900px;
  /* background: url(https://cdn.jsdelivr.net/gh/moezx/cdn@3.1.9/img/Sakura/images/scroll.png) no-repeat center; */
  background: url(/images/scroll.png) no-repeat center;
  background-size: contain;
  -webkit-transition: all .5s ease-in-out;
  transition: all .5s ease-in-out;
  /* cursor: url(https://cdn.jsdelivr.net/gh/moezx/cdn@3.1.9/img/Sakura/cursor/No_Disponible.cur), auto; */
  cursor: url(/images/cursor/No_Disponible.cur), auto;
  opacity: 1
}

.cd-top.cd-is-visible {
  opacity: 1;
  top: -326px
}

.cd-top.cd-fade-out {
  opacity: 1
}

.cd-top:hover {
  opacity: 1
}

.cd-top span {
  display: none;
  color: #000;
  position: absolute;
  bottom: 0;
  height: 20px;
  width: 50px;
  text-align: center
}

@media screen and (max-width:860px) {
  .cd-top {
      display: none;
      height: 60px;
      width: 50px
  }
  .cd-top span {
      height: 10px;
      width: 50px
  }
}

#moblieGoTop {
  display: none;
  position: fixed;
  bottom: 10px;
  right: 10px;
  z-index: 99;
  border: 0;
  outline: 0;
  background-color: #fff;
  color: #404040;
  cursor: pointer;
  padding: 15px;
  border-radius: 10px;
  border-radius: 12px;
  box-shadow: 0 0 2px 0 rgba(0, 0, 0, .12), 0 2px 2px 0 rgba(0, 0, 0, .24);
  transition: box-shadow .2s ease
}
#moblieGoTop:hover {
  background-color: #fff;
  opacity: .8
}
.changeSkin-gear {
  position: fixed;
  bottom: 0;
  left: auto;
  right: 5px;
  width: auto;
  height: auto;
  z-index: 99;
  white-space: nowrap;
  padding: 10px 10px;
  cursor: pointer;
  border-radius: 10px 10px 0 0
}
</style>

<!-- 添加小猫置顶 -->
<a class="cd-top faa-float animated cd-is-visible cd-fade-out" style="top: -500px;"></a>
<button id="moblieGoTop" title="Go to top" style="display: none;font-size: xx-large;"><i class="fa fa-chevron-up" aria-hidden="true"></i>🔝</button>

<!-- <div class="scroll "> <i class="fa fa-arrow-up" style="margin-left: 4px;"></i>
Top⬆️
<span class="scrollpercent" style="margin-left: -2px;"></span>
<span style="margin-right: 4px; margin-left: -4px;">%</span>
</div> -->

<!-- https://www.huangpinke.com/2018/08/24/add-back-to-top-button.html -->
      <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
if (!window.jQuery) {
var script = document.createElement('script');
script.src = "/js/jquery-2.0.3.min.js";
document.body.write(script);
}
</script>

  
<link rel="stylesheet" href="../../../../fancybox/jquery.fancybox.css">

  
<script src="../../../../fancybox/jquery.fancybox.pack.js"></script>




<script src="../../../../js/script.js"></script>




<script>
  (function(){
      var bp = document.createElement('script');
      bp.src = '//push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
  })();
  </script>

<!-- mermaid图 -->

  <script src='https://unpkg.com/mermaid@7.1.2/dist/mermaid.min.js'></script>
  <script>
    if (window.mermaid) {
      mermaid.initialize({theme: 'forest'});
    }
  </script>

    </div>
    <nav id="mobile-nav" class="mobile-nav-box">
  <div class="mobile-nav-img mobile-nav-top"></div>
  
    <a href="../../../../index.html" class="mobile-nav-link">首页</a>
  
    <a href="../../../../archives" class="mobile-nav-link">归档</a>
  
    <a href="../../../../quick-notes" class="mobile-nav-link">小抄</a>
  
    <a href="../../../../about" class="mobile-nav-link">关于</a>
  
  <div class="mobile-nav-img  mobile-nav-bottom"></div>
</nav>    
  </div>
</body>

</html>